package top

import chisel3._
import chisel3.util.experimental.BoringUtils
import chisel3.stage.ChiselGeneratorAnnotation
import firrtl.options.TargetDirAnnotation
import common.Constants._
import bus._
import device._
import system.MySoC
import utils._
import yycore.{MyCore, MyCoreConfig}

class DiffTestIO extends Bundle {
  val r = Output(Vec(32, UInt(64.W)))
  val commit = Output(Bool())
  // val isMultiCommit = Output(Bool())
  val thisPC = Output(UInt(64.W))
  val thisINST = Output(UInt(32.W))
  val isMMIO = Output(Bool())
  val isRVC = Output(Bool())
  // val isRVC2 = Output(Bool())
  val intrNO = Output(UInt(64.W))

  val priviledgeMode = Output(UInt(2.W))
  val mstatus = Output(UInt(64.W))
  // val sstatus = Output(UInt(64.W))
  val mepc = Output(UInt(64.W))
  // val sepc = Output(UInt(64.W))
  val mcause = Output(UInt(64.W))
  // val scause = Output(UInt(64.W))
}

//  class LogCtrlIO() extends Bundle {
//    val log_begin, log_end = Input(UInt(64.W))
//    val log_level = Input(UInt(64.W)) // a cpp uint
//  }

class MySoCSim()  extends Module {
  val io = IO(new Bundle() {
    val difftest = new DiffTestIO
//      val logCtrl = new LogCtrlIO
    val difftestCtrl = new DiffTestCtrlIO
  })

  //lazy val config = MyCoreConfig(FPGA = false)

  val soc = Module(new MySoC())
  val device = Module(new device())

  soc.io.interrupt := DontCare
  soc.io.slave := DontCare
  //soc.io.master <> device.io.in
  soc.io.master.arready := device.io.in.ar.ready
  device.io.in.ar.valid := soc.io.master.arvalid
  device.io.in.ar.bits.addr := soc.io.master.araddr
  device.io.in.ar.bits.id := soc.io.master.arid
  device.io.in.ar.bits.len := soc.io.master.arlen
  device.io.in.ar.bits.burst := soc.io.master.arburst
  device.io.in.ar.bits.size := soc.io.master.arsize

  device.io.in.r.ready := soc.io.master.rready
  soc.io.master.rvalid := device.io.in.r.valid
  soc.io.master.rdata := device.io.in.r.bits.data
  soc.io.master.rlast := device.io.in.r.bits.last
  soc.io.master.rid := device.io.in.r.bits.id
  soc.io.master.rresp := device.io.in.r.bits.resp

  soc.io.master.awready := device.io.in.aw.ready
  device.io.in.aw.valid := soc.io.master.awvalid
  device.io.in.aw.bits.addr := soc.io.master.awaddr
  device.io.in.aw.bits.id := soc.io.master.awid
  device.io.in.aw.bits.len := soc.io.master.awlen
  device.io.in.aw.bits.burst := soc.io.master.awburst
  device.io.in.aw.bits.size := soc.io.master.awsize

  soc.io.master.wready := device.io.in.w.ready
  device.io.in.w.valid := soc.io.master.wvalid
  device.io.in.w.bits.data := soc.io.master.wdata
  device.io.in.w.bits.last := soc.io.master.wlast
  device.io.in.w.bits.strb := soc.io.master.wstrb

  device.io.in.b.ready := soc.io.master.bready
  soc.io.master.bvalid := device.io.in.b.valid
  soc.io.master.bid := device.io.in.b.bits.id
  soc.io.master.bresp := device.io.in.b.bits.resp


  val difftest = WireInit(0.U.asTypeOf(new DiffTestIO))
  BoringUtils.addSink(difftest.commit, "difftestCommit")
  // BoringUtils.addSink(difftest.isMultiCommit, "difftestMultiCommit")
  BoringUtils.addSink(difftest.thisPC, "difftestThisPC")
  BoringUtils.addSink(difftest.thisINST, "difftestThisINST")
  BoringUtils.addSink(difftest.isMMIO, "difftestIsMMIO")
  BoringUtils.addSink(difftest.isRVC, "difftestIsRVC")
  // BoringUtils.addSink(difftest.isRVC2, "difftestIsRVC2")
  BoringUtils.addSink(difftest.intrNO, "difftestIntrNO")
  BoringUtils.addSink(difftest.r, "difftestRegs")
  BoringUtils.addSink(difftest.priviledgeMode, "difftestMode")
  BoringUtils.addSink(difftest.mstatus, "difftestMstatus")
  // BoringUtils.addSink(difftest.sstatus, "difftestSstatus")
  BoringUtils.addSink(difftest.mepc, "difftestMepc")
  // BoringUtils.addSink(difftest.sepc, "difftestSepc")
  BoringUtils.addSink(difftest.mcause, "difftestMcause")
  // BoringUtils.addSink(difftest.scause, "difftestScause")
  io.difftest := difftest

  io.difftestCtrl.enable := true.B
}






